import Cookie from '@/utils/Cookie.js'
import { Http } from '@/service/Http/index.js'
import store from '@/store/index.js'
import LS from '@/utils/LocalStorage.js'
import _ from '@/libs/lodash.min.js'
import LoginVerifyModal from '@/components/User/LoginVerifyModal.js'
import Utils from '@/utils/Utils.js'
import ModalApi from '@/components/SwModal/api.js'
import router from '@/router/index.js'

// 使用vuex+localStorage+cookie组合，vuex作全局用户信息，localStorage作用户信息存储，cookie作当关闭浏览器时使登录过期
// 使用localStorage的userInfo的时候需要获取cookie的isLogged判断是否登录状态
// 正常登录是直接调用.login((loginState, next, isLastOk) => { next() })
// 但本网站登录流程较为复杂，需要操作下面的参数
// loginState是登录状态，next是登录状态对应的下一步动作，isLastOk表示上一次动作是否执行成功
// 本程序将登录流程拆分了很多步骤，可应用在各种场景
// 重点：在调用checkIn（这个方法才是最终的登录，用于把用户信息存入userInfo，此时userInfo才是真正可用的）之前操作和判断的数据都是用userInfo.tempUserInfo

// 登录服务用单例模式
let LoginService = {
  // 用户信息
  userInfo: {},
  loginCallback: null,
  // 获取登录状态
  getLoginState () {
    let userInfo = this.userInfo
    let tempUserInfo = this.userInfo.tempUserInfo

    // 已登录
    if (userInfo.isLogged) {
      return 'logged'
    }

    // 需要提交登录信息调接口
    if (_.isEmpty(userInfo)) {
      return 'needSubmit'
    }

    // 需要设置PIN
    if (tempUserInfo && tempUserInfo.NeedToSetSecurifyPwd) {
      return 'needSetPIN'
    } else {
      router.push({path: '/user/login', query: {from: router.app._route.query.from}})
    }

    // 101异地登录需要短信验证码 102需要谷歌验证码 103是101和102的集合
    // 101:remoteVerify 102:googleVerify 103:googleAndRemoteVerify
    if (tempUserInfo && tempUserInfo.SecurityVerifyType === 101 && tempUserInfo.IsRemoteLogin) {
      return 'needVerify' // 'needRemoteVerify'
    }
    if (tempUserInfo && tempUserInfo.SecurityVerifyType === 102) {
      return 'needVerify' // 'needGoogleVerify'
    }
    if (tempUserInfo && tempUserInfo.SecurityVerifyType === 103 && tempUserInfo.IsRemoteLogin) {
      return 'needVerify' // 'needGoogleAndRemoteVerify'
    }

    // 已登录成功，需要保存用户信息
    return 'needCheckIn'
  },
  // 返回登录状态相应的下一步操作
  getNext (loginState) {
    // 提交
    if (loginState === 'needSubmit') {
      return (params) => {
        this.submit(params).then((res) => {
          this.stateChange(res.isOk)
        })
      }
    }

    // 设置PIN
    if (loginState === 'needPIN') {
      // router.push('/safety/setPin')
      return (params) => {
        this.setPIN(params).then((res) => {
          this.stateChange(res.isOk)
        })
      }
    }

    // 验证
    if (loginState === 'needVerify') {
      return () => {
        this.verify((isPass) => {
          this.stateChange(isPass)
        })
      }
    }

    // 登记用户信息
    if (loginState === 'needCheckIn') {
      return () => {
        this.checkIn()
        this.stateChange(true)
      }
    }

    // 已登录
    if (loginState === 'logged') {
      return undefined
    }
  },
  // 登录（保存原始登录信息和精简用户信息）
  login (cb) {
    this.loginCallback = cb
    this.clearUserInfo()
    this.stateChange(true)
  },
  // 走登录流程并回调（提交表单、设置PIN、需要验证、登记用户信息）
  stateChange (isOk) {
    let loginState = this.getLoginState()
    this.loginCallback(loginState, this.getNext(loginState), isOk)
  },
  // 提交
  submit: function (params) {
    let url = params.password ? 'Customer/SignIn' : 'Customer/CodeSignIn'
    let p = Utils.makePromise()
    Http.post(url, params, {
      isDisposeCode: false
    }).then((res) => {
      // 只有200和密码错误次数为0才通过
      if (res.isOk) {
        this.fakeCheckIn(res.Data)
      } else {
        // 有密码错误次数
        if (res.StatusCode === '42019' || res.StatusCode === '42056' || res.StatusCode === '42057') {
          ModalApi.message(store.state.lang.lang[res.StatusCode])
        } else if (res.Data && res.Data.LoginFaiureCount > 0) {
          if (res.Data.LoginFaiureCount < 5) {
            let lang = store.state.lang.lang['Incorrect password entered 3 times']
            ModalApi.message(lang.replace('{number}', 5 - res.Data.LoginFaiureCount).replace('{attempt}', ((5 - res.Data.LoginFaiureCount) === 1) ? 'attempt' : 'attempts'))
          }
          if (res.Data && res.Data.LoginFaiureCount >= 5) {
            ModalApi.message(store.state.lang.lang['Password locked, please try again in 2 hours'])
          }
        } else {
          // 其它错误
          ModalApi.message(store.state.lang.lang[res.StatusCode])
        }
      }
      p.resolveHandle(res)
    })
    return p
  },
  // 设置PIN
  setPIN (params) {
    let p = Utils.makePromise()
    Http.post('Customer/SetSafePwd', params).then((res) => {
      if (res.isOk) {
        this.clearPINFlag(this.userInfo)
      }
      p.resolveHandle(res)
    })
    return p
  },
  // 验证
  verify (cb) {
    let type = this.userInfo.tempUserInfo.SecurityVerifyType
    let loginVerifyModalHandle = LoginVerifyModal(type, this.userInfo.tempUserInfo, (isPass) => {
      // 读取verify状态，若通过则真正登录
      if (isPass) {
        this.clearVerifyFlag()
        loginVerifyModalHandle.close()
      }
      _.isFunction(cb) && cb(isPass)
    })
  },
  // 登记用户信息
  checkIn (userInfo) { // userInfo是来自外部登录
    if (userInfo) {
      this.userInfo = userInfo
    } else {
      this.userInfo = this.userInfo.tempUserInfo
      delete this.userInfo.tempUserInfo
    }
    this.userInfo.isLogged = true
    this.saveUserInfo(this.userInfo)
  },
  // 登出（清空登录信息）
  logout: function () {
    Http.post('Customer/SignOut')
    this.clearUserInfo()
  },
  // 伪登入，将接口返回的用户信息放在temp
  fakeCheckIn (userInfo) {
    this.userInfo.token = userInfo.Token
    this.userInfo.tempUserInfo = userInfo
    this.saveUserInfo(this.userInfo)
  },
  // 保存用户信息
  saveUserInfo: function (userInfo) {
    // 后端某些命名换成我们前端的命名方式
    userInfo.token = userInfo.Token || userInfo.token // ||后面那层是来自于本对象state.userInfo
    userInfo.userName = userInfo.Account || userInfo.userName
    userInfo.realName = userInfo.RealName || userInfo.realName
    userInfo.userId = userInfo.ID || userInfo.userId
    userInfo.phone = userInfo.Phone || userInfo.phone

    this.userInfo = userInfo
    store.dispatch('saveUserInfo', userInfo)
    Cookie.set('isLogged', true)
    LS.set('userInfo', this.userInfo)
  },
  // 清空用户信息
  clearUserInfo () {
    this.userInfo = {}
    store.dispatch('saveUserInfo', this.userInfo)
    Cookie.del('isLogged')
    LS.remove('userInfo')
  },
  // 设置PIN后把需要设置PIN的标志清空
  clearPINFlag () {
    this.userInfo.tempUserInfo.NeedToSetSecurifyPwd = false
    this.saveUserInfo(this.userInfo)
  },
  // 验证完后将需要验证的标志清空，100是正常状态即不需要验证
  clearVerifyFlag () {
    this.userInfo.tempUserInfo.SecurityVerifyType = 100
    this.saveUserInfo(this.userInfo)
  },
  // 页面一加载就从本地读取用户信息
  init () {
    let localUserInfo = LS.get('userInfo') || {}
    let isLogged = Cookie.get('isLogged')
    // 产品的要求是关闭浏览器时就是退出，当下次打开网站时是退出状态
    // 当cookie不设置时间时，它的生命周期就是浏览器关闭前，关闭浏览器后自动清空，可以利用cookie这一特性实现产品这个要求
    // 当cookie变量---isLogged不存在时，则设置userInfo为空
    // 本程序会将userInfo存放在vuex里，因此在vue应用程序里可以用this.mixUserInfo.userName是否存在来判断用户是否已经登录
    if (!isLogged) {
      this.clearUserInfo()
    } else {
      this.saveUserInfo(localUserInfo)
    }
  }
}

export default LoginService
